package org.lemon.cla.config;


import org.lemon.cla.exception.JwtAuthenticationEntryPoint;
import org.lemon.cla.exception.handler.CustomAccessDeniedHandler;
import org.lemon.cla.filter.JwtAuthenticationFilter;

import org.lemon.cla.serviceImp.UserDetailsServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity
@EnableMethodSecurity // 启用方法安全，以便 @PreAuthorize 生效
public class SecurityConfig {

    private final UserDetailsServiceImpl userDetailsService;
    private final JwtAuthenticationFilter jwtAuthFilter; // JWT 过滤器
    private final JwtAuthenticationEntryPoint unauthorizedHandler; // 未认证处理器（处理 401）
    private final CustomAccessDeniedHandler customAccessDeniedHandler; // 你的自定义访问拒绝处理器（处理 403）

    // 通过构造函数注入所有依赖
    public SecurityConfig(UserDetailsServiceImpl userDetailsService,
                          JwtAuthenticationFilter jwtAuthFilter,
                          JwtAuthenticationEntryPoint unauthorizedHandler,
                          CustomAccessDeniedHandler customAccessDeniedHandler) { // 注入 CustomAccessDeniedHandler
        this.userDetailsService = userDetailsService;
        this.jwtAuthFilter = jwtAuthFilter;
        this.unauthorizedHandler = unauthorizedHandler;
        this.customAccessDeniedHandler = customAccessDeniedHandler; // 赋值
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public DaoAuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
        authProvider.setUserDetailsService(userDetailsService);
        authProvider.setPasswordEncoder(passwordEncoder());
        return authProvider;
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                .csrf(AbstractHttpConfigurer::disable) // 禁用 CSRF
                .exceptionHandling(exception -> exception
                        .authenticationEntryPoint(unauthorizedHandler) // 处理未认证异常 (401 Unauthorized)
                        .accessDeniedHandler(customAccessDeniedHandler) // <-- 处理权限不足异常 (403 Forbidden)
                )
                .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) // 设置无状态会话
                .authorizeHttpRequests(auth -> auth
                        // 允许公共访问的认证接口（登录/注册等）
                        .requestMatchers("/auth/**").permitAll() // 假设你的 JWT 认证接口在此路径下
                        .requestMatchers("/error").permitAll() // 通用错误页面
                        // 允许访问 Knife4j 和 Swagger UI 相关接口
                        .requestMatchers("/v3/api-docs/**", "/swagger-ui/**", "/swagger-resources/**", "/webjars/**", "/knife4j/**", "/doc.html").permitAll()
                        // 其他所有请求都需要认证
                        .anyRequest().authenticated()
                )
                .authenticationProvider(authenticationProvider()) // 使用你自定义的认证提供者
                .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class); // 将 JWT 过滤器添加到 Spring 默认过滤器之前

        return http.build();
    }

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }
}